package jehc.djshi.actuator.web;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jehc.djshi.actuator.jvm.JMapUtil;
import jehc.djshi.actuator.jvm.JStackUtil;
import jehc.djshi.actuator.jvm.JStatUtil;
import jehc.djshi.actuator.util.ServerUtil;
import jehc.djshi.actuator.model.*;
import jehc.djshi.actuator.model.Thread;
import jehc.djshi.actuator.util.ExecuteCmd;
import jehc.djshi.actuator.util.LogReaderUtils;
import jehc.djshi.actuator.vo.KV;
import jehc.djshi.common.annotation.Auth;
import jehc.djshi.common.base.BaseResult;
import jehc.djshi.actuator.util.ActuatorSDKUtil;
import jehc.djshi.common.util.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
/**
 * @Desc WEB服务应用Client
 * @Author 邓纯杰
 * @CreateTime 2013-10-05 17:15:42
 */
@RestController
@RequestMapping("/actuator/info")
@Api(value = "WEB服务应用Client",tags = "WEB服务应用Client",description = "WEB服务应用Client")
@Slf4j
public class ActuatorClient {

	@Value("${jehc.omp.actuator.log.path:}")
	private String actuatorLogPath;

	@Resource
    ActuatorSDKUtil actuatorSDKUtil;

    /**
     * 线程信息
     * @return
     */
    @ApiOperation(value="线程信息", notes="线程信息")
    @GetMapping("/thread")
    @Auth(value = "/actuator/info/thread",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult thread(){
        String date = DateUtil.time();
        try {
            JStack jstack = JStackUtil.jstack();
            Thread thread = new Thread();
            thread.setId(Integer.valueOf(jstack.getId()));
            thread.setName(actuatorSDKUtil.getProjectName());
            thread.setEnv(actuatorSDKUtil.getEnviron());
            thread.setDate(date);
            thread.setTotal(jstack.getTotal());
            thread.setRunnable(jstack.getRunnable());
            thread.setTimedWaiting(jstack.getTimedWaiting());
            thread.setWaiting(jstack.getWaiting());
            return BaseResult.success(thread);
        }catch (Exception e){
            log.debug("RuntimeExec异常：{}",e);
            return BaseResult.fail();
        }
    }

    /**
     * 类加载信息
     * @return
     */
    @ApiOperation(value="类加载信息", notes="类加载信息")
    @GetMapping("/classLoad")
    @Auth(value = "/actuator/info/classLoad",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult<ClassLoad> classLoad(){
        String date = DateUtil.time();
        try {
            List<KV> jstatClass = JStatUtil.jstatClass();
            ClassLoad classLoad = new ClassLoad();
            classLoad.setId(Integer.valueOf(ActuatorSDKUtil.getPid()));
            classLoad.setName(actuatorSDKUtil.getProjectName());
            classLoad.setEnv(actuatorSDKUtil.getEnviron());
            classLoad.setDate(date);
            classLoad.setLoaded(jstatClass.get(0).getValue());
            classLoad.setBytes1(jstatClass.get(1).getValue());
            classLoad.setUnloaded(jstatClass.get(2).getValue());
            classLoad.setBytes2(jstatClass.get(3).getValue());
            classLoad.setTime1(jstatClass.get(4).getValue());
            classLoad.setCompiled(jstatClass.get(5).getValue());
            classLoad.setFailed(jstatClass.get(6).getValue());
            classLoad.setInvalid(jstatClass.get(7).getValue());
            classLoad.setTime2(jstatClass.get(8).getValue());
            return BaseResult.success(classLoad);
        }catch (Exception e){
            log.debug("RuntimeExec异常：{}",e);
            return  BaseResult.fail();
        }
    }

    /**
     * GC信息
     * @return
     */
    @ApiOperation(value="GC信息", notes="GC信息")
    @GetMapping("/gc")
    @Auth(value = "/actuator/info/gc",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult<Gc> gc(){
        String date = DateUtil.time();
        try {
            List<KV> kvEntities = JStatUtil.jstatGc();
            Gc gc = new Gc();
            gc.setId(Integer.valueOf(ActuatorSDKUtil.getPid()));
            gc.setName(actuatorSDKUtil.getProjectName());
            gc.setEnv(actuatorSDKUtil.getEnviron());
            gc.setDate(date);
            gc.setS0C(kvEntities.get(0).getValue());
            gc.setS1C(kvEntities.get(1).getValue());
            gc.setS0U(kvEntities.get(2).getValue());
            gc.setS1U(kvEntities.get(3).getValue());
            gc.setEc(kvEntities.get(4).getValue());
            gc.setEu(kvEntities.get(5).getValue());
            gc.setOc(kvEntities.get(6).getValue());
            gc.setOu(kvEntities.get(7).getValue());
            gc.setMc(kvEntities.get(8).getValue());
            gc.setMu(kvEntities.get(9).getValue());
            gc.setCcsc(kvEntities.get(10).getValue());
            gc.setCcsu(kvEntities.get(11).getValue());
            gc.setYgc(kvEntities.get(12).getValue());
            gc.setYgct(kvEntities.get(13).getValue());
            gc.setFgc(kvEntities.get(14).getValue());
            gc.setFgct(kvEntities.get(15).getValue());
            gc.setGct(kvEntities.get(16).getValue());
            return BaseResult.success(gc);
        }catch (Exception e){
            log.debug("RuntimeExec异常：{}",e);
            return  BaseResult.fail();
        }
    }

    /**
     * 执行自定义命令 linux命令
         Map<String, String> params = new HashMap<String, String>();
         params.put("name", "free");
         params.put("value", "-m");
     * @return
     */
    @ApiOperation(value="执行自定义命令", notes="执行自定义命令")
    @PostMapping("/executeExec")
    @Auth(value = "/actuator/info/executeExec",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult executeExec(@RequestBody Map<String, String> params){
        try{
            ArrayList<String> list = new ArrayList<>();
            for(String s:params.keySet()){
                list.add(params.get(s));
            }
            String[] array = (String[])list.toArray(new String[list.size()]);
            log.debug("RunExec:{}", Arrays.toString(array));
            String result = ExecuteCmd.execute(array);
            return BaseResult.success(result);
        }catch (Exception e){
            log.debug("RuntimeExec异常：{}",e);
            return BaseResult.fail("RuntimeExec异常");
        }
    }

    /**
     * 系统物理内存 
     * @return
     */
    @ApiOperation(value="系统物理内存", notes="系统物理内存")
    @GetMapping("/systemInfo")
    @Auth(value = "/actuator/info/systemInfo",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult systemInfo() {
		try {
		    ServerUtil serverUtil = new ServerUtil();
			return BaseResult.success(serverUtil.getSystemInfo());
		} catch (Exception e) {
            log.error("systemInfo异常：{}",e);
            return BaseResult.fail("systemInfo异常");
		}
    }

    /**
     * 读取日志
     * @return
     */
    @ApiOperation(value="读取日志", notes="读取日志")
    @GetMapping("/logReader")
    @Auth(value = "/actuator/info/logReader",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult logReader(){
        try{
            String message = LogReaderUtils.poll(actuatorLogPath);
            return BaseResult.success(message);
        }catch (Exception e){
            log.debug("RuntimeExec异常：{}",e);
            return BaseResult.fail("RuntimeExec异常");
        }
    }

//    /**
//     * 堆栈快照
//     * @return
//     * @throws IOException
//     */
//    @GetMapping("/heap/dump")
//    @AuthUneedLogin
//    @ApiOperation(value="堆栈快照导出", notes="堆栈快照导出")
//    public ResponseEntity<byte[]> heapDump() throws IOException {
//        String dump = JMapUtil.dump();
//        File file = new File(dump);
//        log.debug("DownLoad Dump:"+dump);
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//        headers.setContentDispositionFormData("attachment", file.getName());
//        return new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
//    }

    /**
     * 堆栈快照
     * @return
     * @throws IOException
     */
    @ApiOperation(value="堆栈快照导出", notes="堆栈快照导出")
    @GetMapping("/heap/dump")
    @Auth(value = "/actuator/info/heap/dump",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public synchronized void heapDump(HttpServletResponse response){
        File file = null;
        try {
            String dump = JMapUtil.dump();
            file = new File(dump);
            if(file.exists()){
                log.debug("DownLoad Dump:"+dump);
                int len=0;
                byte []buffers = new byte[1024];
                BufferedInputStream br = null;
                OutputStream ut = null;
                response.reset();
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setContentType("application/x-msdownload");
                response.setHeader("Content-Disposition","attachment;filename=" +java.net.URLEncoder.encode(file.getName(),"UTF-8"));
                br = new BufferedInputStream(new FileInputStream(file));
                ut = response.getOutputStream();
                while((len=br.read(buffers))!=-1){
                    ut.write(buffers, 0, len);
                }
                ut.flush();
                ut.close();
                br.close();
            }else{
                response.getWriter().println("<script type='text/javascript'>top.window.parent.toastrBoot(4,'<font color=red>您访问的文件已经不存在，请联系管理员！</font>');</script>");
            }
        }catch (Exception e){
            log.error("导出堆快照异常：{}",e);
        }finally {
            if(null != file && file.exists()){
                file.delete();
            }
        }
    }

//    /**
//     * 线程快照
//     * @return
//     * @throws IOException
//     */
//    @GetMapping("/thread/dump")
//    @ApiOperation(value="线程快照", notes="线程快照")
//    @AuthUneedLogin
//    public ResponseEntity<byte[]> threadDump() throws IOException {
//        String dump = JStackUtil.dump();
//        File file = new File(dump);
//        log.debug("DownLoad Dump:"+dump);
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//        headers.setContentDispositionFormData("attachment", file.getName());
//        return new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
//    }

    /**
     * 导出线程快照
     * @return
     * @throws IOException
     */
    @ApiOperation(value="导出线程快照", notes="导出线程快照")
    @GetMapping("/thread/dump")
    @Auth(value = "/actuator/info/thread/dump",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public synchronized void threadDump(HttpServletResponse response){
        File file = null;
        try {
            String dump = JStackUtil.dump();
            file = new File(dump);
            if(file.exists()){
                log.debug("DownLoad Dump:"+dump);
                int len=0;
                byte []buffers = new byte[1024];
                BufferedInputStream br = null;
                OutputStream ut = null;
                response.reset();
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setContentType("application/x-msdownload");
                response.setHeader("Content-Disposition","attachment;filename=" +java.net.URLEncoder.encode(file.getName(),"UTF-8"));
                br = new BufferedInputStream(new FileInputStream(file));
                ut = response.getOutputStream();
                while((len=br.read(buffers))!=-1){
                    ut.write(buffers, 0, len);
                }
                ut.flush();
                ut.close();
                br.close();
            }else{
                response.getWriter().println("<script type='text/javascript'>top.window.parent.toastrBoot(4,'<font color=red>您访问的文件已经不存在，请联系管理员！</font>');</script>");
            }
        }catch (Exception e){
            log.error("导出堆快照异常：{}",e);
        }finally {
            if(null != file && file.exists()){
                file.delete();
            }
        }
    }
}
